package com.ruicar.afs.cloud.manage.common.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruicar.afs.cloud.basic.api.corporate.dto.ReceiptCancelAgreeDto;
import com.ruicar.afs.cloud.basic.api.corporate.fegin.CorporateTransferFeign;
import com.ruicar.afs.cloud.basic.api.corporate.fegin.InterFaceGroupFeign;
import com.ruicar.afs.cloud.common.core.constant.CommonConstants;
import com.ruicar.afs.cloud.common.core.enums.AfsEnumUtil;
import com.ruicar.afs.cloud.common.core.exception.AfsBaseException;
import com.ruicar.afs.cloud.common.core.security.util.SecurityUtils;
import com.ruicar.afs.cloud.common.core.util.IResponse;
import com.ruicar.afs.cloud.common.modules.contract.enums.*;
import com.ruicar.afs.cloud.common.util.EmptyUtils;
import com.ruicar.afs.cloud.manage.common.entity.ManageApplyRecord;
import com.ruicar.afs.cloud.manage.common.entity.ManageCollectCancel;
import com.ruicar.afs.cloud.manage.common.entity.ManagePrepaymentApply;
import com.ruicar.afs.cloud.manage.common.mapper.ManageCollectCancelMapper;
import com.ruicar.afs.cloud.manage.common.service.*;
import com.ruicar.afs.cloud.manage.common.util.CreatCaseNoUtil;
import com.ruicar.afs.cloud.manage.finance.bankarrive.entity.ManageAccountRegister;
import com.ruicar.afs.cloud.manage.finance.bankarrive.service.ManageAccountRegisterService;
import com.ruicar.afs.cloud.manage.finance.corporate.entity.ManageCorporateTransfer;
import com.ruicar.afs.cloud.manage.finance.corporate.service.ManageCorporateTransferService;
import com.ruicar.afs.cloud.manage.revoke.condition.ManageCollectCancelCondition;
import com.ruicar.afs.cloud.manage.revoke.vo.ManageCollectCancelVo;
import com.ruicar.afs.cloud.manage.revoke.vo.ManageRevokeHandleVo;
import com.ruicar.afs.cloud.manage.workflow.enums.NormalSubmitEnum;
import com.ruicar.afs.cloud.manage.workflow.enums.WorkflowTypeEnum;
import com.ruicar.afs.cloud.manage.workflow.processor.ContractWorkFlowSaveApproveInfoProcessor;
import com.ruicar.afs.cloud.manage.workflow.service.WorkTaskCreatedInfoService;
import com.ruicar.afs.cloud.manage.workflow.service.WorkflowSubmitService;
import com.ruicar.afs.cloud.manage.workflow.vo.TaskSubmitVO;
import com.ruicar.afs.cloud.workflow.api.dto.flowprocess.request.StartFlowRequest;
import com.ruicar.afs.cloud.workflow.gwt.service.WorkflowService;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.MessageFormat;
import java.util.Date;
import java.util.List;

/**
 * @author: Lee
 * @date 2020-05-30 04:45:15
 * @description
 */
@Service
@AllArgsConstructor
public class ManageCollectCancelServiceImpl extends ServiceImpl<ManageCollectCancelMapper, ManageCollectCancel> implements ManageCollectCancelService {
    private final ContractWorkFlowSaveApproveInfoProcessor saveApproveInfoProcessor;
    private final WorkflowService workflowService;
    private final WorkTaskCreatedInfoService workTaskCreatedInfoService;
    private final WorkflowSubmitService workflowSubmitService;
    private final CorporateTransferFeign corporateTransferFeign;
    private final InterFaceGroupFeign interFaceGroupFeign;
    private final ManageCorporateTransferService manageCorporateTransferService;
    private final ComAttachementFileService comAttachementFileService;
    private final ContractWorkFlowSaveApproveInfoProcessor contractWorkFlowSaveApproveInfoProcessor;
    private final ManageAccountRegisterService manageAccountRegisterService;
    private final ManageOverpaymentDifferenceService manageOverpaymentDifferenceService;
    private final ManagePrepaymentApplyService managePrepaymentApplyService;
    private final ManageApplyRecordService manageApplyRecordService;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean revokedStartProcess(ManageCollectCancelVo vo) {
        //根据收据id查询撤销收款信息表
        List<ManageCollectCancel> list = this.list(Wrappers.<ManageCollectCancel>lambdaQuery().eq(ManageCollectCancel::getReceiptId, vo.getReceiptId()).ne(ManageCollectCancel::getCaseStatus, CaseStatusEnum.REFUSE));
        if (CollectionUtil.isNotEmpty(list)) {
            ManageCollectCancel collectCancel = list.get(0);
            if (CaseStatusEnum.UNDER_REVIEW.equals(collectCancel.getCaseStatus())) {
                log.error("该收款已在撤销流程中，不可重复撤销！");
                throw new AfsBaseException("该收款已在撤销流程中，不可重复撤销！");
            }
        }
        vo.setCaseStatus(CaseStatusEnum.UNDER_REVIEW);
        vo.setStartTime(new Date());
        vo.setProcessStatus(ProcessStatusEnum.underReview);
        ManageCollectCancel cancel = new ManageCollectCancel();
        if (vo.getId() != null) {
            cancel = this.getById(vo.getId());
            if (!ProcessStatusEnum.draft.equals(cancel.getProcessStatus())) {
                log.error("该收款已在撤销流程中，不可重复撤销！");
                throw new AfsBaseException("该收款已在撤销流程中，不可重复撤销！");
            }
            vo.setCaseNo(cancel.getCaseNo());
            BeanUtil.copyProperties(vo, cancel, "createBy", "createTime", "id");
            this.updateById(cancel);
            vo.setId(cancel.getId());
        } else {
            cancel = new ManageCollectCancel();
            // 生成案件编号
            vo.setCaseNo(CreatCaseNoUtil.GeneratorCaseNo(ContractBusinessEnum.collectionRevoke));
            BeanUtil.copyProperties(vo, cancel, "createBy", "createTime", "id");
            this.save(cancel);
            vo.setId(cancel.getId());

        }
        comAttachementFileService.saveFile(cancel.getContractNo(), cancel.getCaseNo(),
                ContractBusinessEnum.collectionRevoke.name());
        vo.setProcessPerson(SecurityUtils.getUser().getUserRealName());
        //保存待办任务记录
        saveApproveInfoProcessor.saveApproveInfo(vo, ContractBusinessEnum.collectionRevoke, CaseStatusEnum.UNDER_REVIEW, BusinessUrlEnum.COLLECTION_REVOKE);
        StartFlowRequest startFlowRequest = new StartFlowRequest();
        startFlowRequest.setAfsFlowKey(AfsEnumUtil.key(WorkflowTypeEnum.COLLECTION_REVOKE));
        startFlowRequest.setBizDataId(String.valueOf(vo.getId()));
        startFlowRequest.setFlowName(AfsEnumUtil.desc(WorkflowTypeEnum.COLLECTION_REVOKE));
        //首次提交发起申请，保存审批历史记录
        contractWorkFlowSaveApproveInfoProcessor.saveApproveRecord(vo, ContractBusinessEnum.collectionRevoke);
        String json = JSONObject.toJSONString(vo);
        JSONObject cancelJson = JSONObject.parseObject(json);
        TaskSubmitVO taskSubmitVO = new TaskSubmitVO();
        taskSubmitVO.setBizData(cancelJson);
        workflowService.startWorkFlow(startFlowRequest, cancelJson);
        IResponse iResponse = corporateTransferFeign.receiptHandleForCancelStart(vo.getReceiptId(), vo.getCaseNo());
        if (!CommonConstants.SUCCESS.equals(iResponse.getCode())) {
            throw new AfsBaseException(MessageFormat.format("收款撤销发起收据处理失败,原因{0}", iResponse.getMsg()));
        }
        return Boolean.TRUE;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean revokeSubmitProcess(ManageCollectCancelVo collectCancelVo) {
        //根据ID查询申请表
        ManageCollectCancel cancel = this.getById(collectCancelVo.getId());
        //更新处理状态
        if (AfsEnumUtil.key(NormalSubmitEnum.SUGGEST_CHECK_FINAL).equals(collectCancelVo.getApprovalOperating())) {
            cancel.setCaseStatus(CaseStatusEnum.APPROVED);
            cancel.setProcessStatus(ProcessStatusEnum.approved);
            cancel.setEndTime(new Date());
            cancel.setEndDate(new Date());
            manageOverpaymentDifferenceService.delete(collectCancelVo.getContactNo());
            //对公结算的，撤销完成需要生成一笔到账登记记录
            if (ReceiptSourceTypeEnum.transferAccounts.equals(cancel.getSourceType())) {
                ManageAccountRegister manageAccountRegister = manageAccountRegisterService.getById(cancel.getSourceId());
                if (manageAccountRegister != null) {
                    manageAccountRegister.setVirtualId(null);
                    manageAccountRegister.setContractNo("");
                    manageAccountRegister.setCaseId(null);
                    manageAccountRegister.setStatus(AccountRegistStatusEnum.ALREADY_GENERA);
                    manageAccountRegisterService.updateById(manageAccountRegister);
                }
            }
            //保存待办任务记录
            saveApproveInfoProcessor.saveApproveInfo(cancel, ContractBusinessEnum.collectionRevoke, CaseStatusEnum.APPROVED, BusinessUrlEnum.COLLECTION_REVOKE);
            /**  发送收款撤销聚合接口 by ZC.GUO  **/
            ReceiptCancelAgreeDto cancelAgreeDto = new ReceiptCancelAgreeDto();
            cancelAgreeDto.setReceiptId(String.valueOf(cancel.getReceiptId()));
            cancelAgreeDto.setRequestId(String.valueOf(cancel.getId()));
            cancelAgreeDto.setOperator(SecurityUtils.getUser().getUsername());
            IResponse iResponse = interFaceGroupFeign.receiptHandleForCancelAgree(cancelAgreeDto);
            if (!CommonConstants.SUCCESS.equals(iResponse.getCode())) {
                throw new AfsBaseException(MessageFormat.format("收款撤销通过收据处理失败,原因{0}", iResponse.getMsg()));
            }
        } else if (AfsEnumUtil.key(NormalSubmitEnum.SUGGEST_REJECT_FINAL).equals(collectCancelVo.getApprovalOperating())) {
            cancel.setCaseStatus(CaseStatusEnum.REFUSE);
            cancel.setProcessStatus(ProcessStatusEnum.refuse);
            cancel.setEndTime(new Date());
            cancel.setEndDate(new Date());
            //保存待办任务记录
            saveApproveInfoProcessor.saveApproveInfo(cancel, ContractBusinessEnum.collectionRevoke, CaseStatusEnum.REFUSE, BusinessUrlEnum.COLLECTION_REVOKE);
            IResponse iResponse = corporateTransferFeign.receiptHandleForCancelReject(cancel.getReceiptId(), SecurityUtils.getUser().getUserRealName());
            if (!CommonConstants.SUCCESS.equals(iResponse.getCode())) {
                throw new AfsBaseException( MessageFormat.format("收款撤销拒绝收据处理失败,原因{0}", iResponse.getMsg()));
            }
        } else if (AfsEnumUtil.key(NormalSubmitEnum.SEND_BACK).equals(collectCancelVo.getApprovalOperating())) {
            //保存待办任务记录
            cancel.setProcessStatus(ProcessStatusEnum.toBeRepaired);
            saveApproveInfoProcessor.saveApproveInfo(cancel, ContractBusinessEnum.collectionRevoke, CaseStatusEnum.UNDER_REVIEW, BusinessUrlEnum.COLLECTION_REVOKE);
        }
        this.updateById(cancel);
        //流程审批
        TaskSubmitVO vo = new TaskSubmitVO();
        collectCancelVo.setCaseNo(cancel.getCaseNo());
        collectCancelVo.setProcessStatus(cancel.getProcessStatus());
        collectCancelVo.setCaseStatus(cancel.getCaseStatus());
        String json = JSONObject.toJSONString(collectCancelVo);
        JSONObject cancelJson = JSONObject.parseObject(json);
        vo.setBizData(cancelJson);
        vo.setApprovalOperating(collectCancelVo.getApprovalOperating());
        vo.setApprovalOpinion(collectCancelVo.getApprovalOpinion());
        vo.setReasonType(collectCancelVo.getReasonType());
        workflowSubmitService.submit(vo);
        return Boolean.TRUE;
    }

    @Override
    public IPage<ManageRevokeHandleVo> getManageHandleList(ManageCollectCancelCondition condition) {
        Page page = new Page(condition.getPageNumber(), condition.getPageSize());
        return this.baseMapper.getManageHandleList(page, condition);
    }

    @Override
    public ManageCollectCancel getManageCollectCancelByCaseNo(String caseNo) {
        return this.getOne(Wrappers.<ManageCollectCancel>query().lambda()
                .eq(ManageCollectCancel::getCaseNo, caseNo), false);
    }

    @Override
    public IPage<ManageRevokeHandleVo> queryManageCollectCancelList(ManageCollectCancelCondition condition) {
        Page page = new Page(condition.getPageNumber(), condition.getPageSize());
        return this.baseMapper.queryManageCollectCancelList(page, condition);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ManageCollectCancel saveCollectCancel(ManageCollectCancelVo collectCancelVo) {
        ManageCollectCancel collectCancel = new ManageCollectCancel();
        if (collectCancelVo.getId() != null) {
            collectCancel = this.getById(collectCancelVo.getId());
            if (!ProcessStatusEnum.draft.equals(collectCancel.getProcessStatus())) {
                Assert.isTrue(false, "收款撤销已在流程中");
            }
            BeanUtil.copyProperties(collectCancelVo, collectCancel, "createBy", "createTime", "id","caseNo");
            this.updateById(collectCancel);
            return collectCancel;
        } else {
            //根据收据id查询撤销收款信息表
            List<ManageCollectCancel> list = this.list(Wrappers.<ManageCollectCancel>lambdaQuery().eq(ManageCollectCancel::getReceiptId, collectCancelVo.getReceiptId()).ne(ManageCollectCancel::getCaseStatus, CaseStatusEnum.REFUSE));
            if (EmptyUtils.isNotEmpty(list)) {
                collectCancel = list.get(0);
                if (!ProcessStatusEnum.draft.equals(collectCancel.getProcessStatus())) {
                    Assert.isTrue(false, "收款撤销已在流程中");
                }
                BeanUtil.copyProperties(collectCancelVo, collectCancel, "createBy", "createTime", "id","caseNo");
                this.updateById(collectCancel);
            } else {
                BeanUtil.copyProperties(collectCancelVo, collectCancel, "createBy", "createTime", "id");
                // 生成案件编号
                collectCancel.setCaseNo(CreatCaseNoUtil.GeneratorCaseNo(ContractBusinessEnum.collectionRevoke));
                collectCancel.setCaseStatus(CaseStatusEnum.NOT_SUBMIT);
                collectCancel.setProcessStatus(ProcessStatusEnum.draft);
                this.save(collectCancel);
            }
            return collectCancel;
        }
    }
    /**
     * 审核通过操作的校验
     * @param
     * @return
     */
    public IResponse<String> agreeValid(ManageCollectCancelVo collectCancelVo) {
        /**  提前结清业务校验（审核总） by ZC.GUO  **/
        List<ManagePrepaymentApply> list = managePrepaymentApplyService.list(Wrappers.<ManagePrepaymentApply>query().lambda()
                .eq(ManagePrepaymentApply::getContractNo,collectCancelVo.getContractNo())
                .eq(ManagePrepaymentApply::getApplyStatus,CaseStatusEnum.UNDER_REVIEW)
        );
        if (EmptyUtils.isNotEmpty(list)){
            return IResponse.fail("提前结清业务审核中，请谨慎操作");
        }
        /**  提前结清业务校验（审核通过，未过还款日） by ZC.GUO  **/
        list = managePrepaymentApplyService.list(Wrappers.<ManagePrepaymentApply>query().lambda()
                .eq(ManagePrepaymentApply::getContractNo,collectCancelVo.getContractNo())
                .eq(ManagePrepaymentApply::getApplyStatus,CaseStatusEnum.APPROVED)
                .eq(ManagePrepaymentApply::getStatus,ValidOrInvalidEnum.valid)
        );
        if (EmptyUtils.isNotEmpty(list)){
            return IResponse.fail("已申请提前结清业务，请谨慎操作！");
        }

        /**  提前结清对公收款（审核中） by ZC.GUO  **/
        List<ManageCorporateTransfer> corporateTransferList = manageCorporateTransferService.list(Wrappers.<ManageCorporateTransfer>query().lambda()
                .eq(ManageCorporateTransfer::getContractNo,collectCancelVo.getContractNo())
                .eq(ManageCorporateTransfer::getCaseStatus,CaseStatusEnum.UNDER_REVIEW)
        );
        if (EmptyUtils.isNotEmpty(corporateTransferList)){
            if (CaseTypeEnum.BEFORE_CHARGE.equals(corporateTransferList.get(0).getCaseType())){
                return IResponse.fail("已申请对公收款（提前结清类）业务，请谨慎操作！");
            }else{
                return IResponse.fail("已申请对公收款（月供类）业务，请谨慎操作！");
            }
        }
        List<ManageApplyRecord> overpayment = manageApplyRecordService.list(Wrappers.<ManageApplyRecord>lambdaQuery()
                .eq(ManageApplyRecord::getContractNo, collectCancelVo.getContractNo() )
                .eq(ManageApplyRecord::getContractBusiness, ContractBusinessEnum.overpayment)
                .eq(ManageApplyRecord::getCaseStatus, CaseStatusEnum.UNDER_REVIEW));
        if (EmptyUtils.isNotEmpty(overpayment)){
            throw new AfsBaseException("溢缴款在审批中，无法审批！");
        }
        /**  豁免类（审核中）  **/
        List<ManageApplyRecord>  records = manageApplyRecordService.list(Wrappers.<ManageApplyRecord>lambdaQuery()
                .eq(ManageApplyRecord::getContractNo, collectCancelVo.getContractNo())
                .in(ManageApplyRecord::getContractBusiness, ContractBusinessEnum.costExempt,ContractBusinessEnum.costExemptBill,ContractBusinessEnum.exemptTypes)
                .eq(ManageApplyRecord::getCaseStatus, CaseStatusEnum.UNDER_REVIEW));
        if (EmptyUtils.isNotEmpty(records)) {
            throw new AfsBaseException("豁免业务审核中，无法审批！");
        }
        return IResponse.success("校验通过");
    }

}
